package impl

import (
	"context"

	"gitee.com/zatto/project/tree/master/vblog/api/apps/blog"
	"gitee.com/zatto/project/tree/master/vblog/api/apps/tag"
	"github.com/imdario/mergo"
)

func (i *impl) CreateBlog(ctx context.Context, req *blog.CreateBlogRequest) (*blog.Blog, error) {
	// 1.请求参数校验
	if err := req.Validate(); err != nil {
		return nil, err
	}

	// 2.通过用户请求参数构建一个blog对象
	ins := blog.NewBlog(req)

	// 3.把blog对象保存到数据库
	if err := i.db.WithContext(ctx).Save(ins).Error; err != nil {
		return nil, err
	}
	return ins, nil
}

func (i *impl) QueryBlog(ctx context.Context, req *blog.QueryBlogRequest) (*blog.BlogSet, error) {
	// 1.创建query对象
	query := i.db.Table("blogs").WithContext(ctx)

	// 2.组装筛选条件
	if req.Status != nil {
		query = query.Where("status = ?", *req.Status)
	}

	if req.Author != "" {
		query = query.Where("author = ?", req.Author)
	}

	if req.Keywords != "" {
		query = query.Where("title LIKE ?", "%"+req.Keywords+"%")
	}

	// 3.查询数据
	set := blog.NewBlogSet()
	err := query.Order("created_at DESC").Offset(req.Offset()).Limit(req.PageSize).Find(&set.Items).Error
	if err != nil {
		return nil, err
	}

	// 4.添加标签
	tagReq := tag.NewQueryTagRequest()
	for index := range set.Items {
		item := set.Items[index]
		tagReq.BlogIds = []int{item.Id}
		ts, err := i.tag.QueryTag(ctx, tagReq)
		if err != nil {
			return nil, err
		}
		item.Tags = ts.Items
	}

	// 5.统计总数
	err = query.Count(&set.Total).Error
	if err != nil {
		return nil, err
	}
	return set, nil
}

func (i *impl) DescribeBlog(ctx context.Context, req *blog.DescribeBlogRequest) (*blog.Blog, error) {
	query := i.db.Table("blogs").WithContext(ctx)

	ins := blog.NewBlog(blog.NewCreateBlogRequest())
	err := query.Where("id = ?", req.Id).First(ins).Error
	if err != nil {
		return nil, err
	}
	tagReq := tag.NewQueryTagRequest()
	tagReq.BlogIds = []int{ins.Id}
	ts, err := i.tag.QueryTag(ctx, tagReq)
	if err != nil {
		return nil, err
	}
	ins.Tags = ts.Items
	return ins, nil
}

func (i *impl) UpdateBlog(ctx context.Context, req *blog.UpdateBlogRequest) (*blog.Blog, error) {
	// 查询旧对象
	ins, err := i.DescribeBlog(ctx, blog.NewDescribeBlogRequest(req.Id))
	if err != nil {
		return nil, err
	}

	// 更新对象
	switch req.UpdateMode {
	// 全量更新
	case blog.PUT:
		ins.CreateBlogRequest = req.CreateBlogRequest

	// 局部更新
	case blog.PATCH:
		err := mergo.MergeWithOverwrite(ins.CreateBlogRequest, req.CreateBlogRequest)
		if err != nil {
			return nil, err
		}
	}

	// 校验更新后的对象是否合法
	if err := ins.CreateBlogRequest.Validate(); err != nil {
		return nil, err
	}

	// 修改更新时间并入库,update_at字段由gorm自动更新
	err = i.db.Table("blogs").WithContext(ctx).Where("id = ?", req.Id).Updates(ins).Error
	if err != nil {
		return nil, err
	}
	return ins, nil
}

func (i *impl) DeleteBlog(ctx context.Context, req *blog.DeleteBlogRequest) (*blog.Blog, error) {
	// 查找对象
	ins, err := i.DescribeBlog(ctx, blog.NewDescribeBlogRequest(req.Id))
	if err != nil {
		return nil, err
	}

	// 删除文章
	err = i.db.Table("blogs").WithContext(ctx).Delete(&blog.Blog{Id: req.Id}).Error
	if err != nil {
		return nil, err
	}

	// 删除标签
	tagReq := tag.NewRemoveTagRequest(req.Id)
	_, err = i.tag.RemoveTag(ctx, tagReq)
	if err != nil {
		return nil, err
	}

	return ins, nil

}
